package com.xhb.ui.http;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.Executors;

import javax.xml.bind.DatatypeConverter;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.teamdev.jxbrowser.deps.com.google.common.collect.Lists;
import com.xhb.ui.tools.BaiduUtil;
import com.xhb.ui.tools.CmdUtil;
import com.xhb.ui.tools.LogFormat;
import com.xhb.ui.tools.PicUtil;
import com.xhb.ui.tools.SortFileUtil;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;

@SuppressWarnings({"restriction","deprecation"})
public class HttpServer {
	
	public static final String BASE_PATH="C://zgymw";

	public void createServer() throws IOException {

		List<Integer> ports = Lists.newArrayList();
		ports.add(8880);

		for (Integer integer : ports) {
			InetSocketAddress addr = new InetSocketAddress(integer);
			com.sun.net.httpserver.HttpServer server = com.sun.net.httpserver.HttpServer.create(addr, 0);
			server.createContext("/", new MyHandler());
			server.setExecutor(Executors.newScheduledThreadPool(200));
			server.start();
		}
	}

	class MyHandler implements HttpHandler {
		
		public void handle(HttpExchange exchange) throws IOException {
			Headers responseHeaders = exchange.getResponseHeaders();
			responseHeaders.set("Content-Type", "text/plain;charset=UTF-8");
			String uri = exchange.getRequestURI().getRawPath();
			if (StringUtils.equals("/", uri)) {
				readFileNameBytes(exchange);
			}
			else if (StringUtils.equals("/video", uri)) {
				readVideo(exchange);
			}
			else if (StringUtils.equals("/firstOrderMotion", uri)) {
				firstOrderMotion(exchange);
			}
			else {
				OutputStream response = exchange.getResponseBody();
				IoUtil.writeObj(response, false, "SUCCESS");
			}
		}
		
		/**
		 * 获取本地视频 浏览器不支持读取本地视频
		 * 
		 * @param exchange
		 * @throws IOException
		 */
		protected void readFileNameBytes(HttpExchange exchange) throws IOException {
			try {
				String name = getQueryParam(exchange, "name");
				{
					LogFormat.info("name :" + name);
				}
				File file = new File(name);

				if (!file.exists()) {
					return;
				}

				byte[] data = FileUtil.readBytes(new File(name));
				Headers responseHeaders = exchange.getResponseHeaders();
				OutputStream response = exchange.getResponseBody();

				long fileSize = data.length;
				// 通知客户端允许断点续传，响应格式为：Accept-Ranges: bytes
				responseHeaders.set("Accept-Ranges", "bytes");
				// 通知客户端使用的是断点续传协议，即返回206状态：
				exchange.sendResponseHeaders(200, fileSize);
				// 文件名
				String fileName = file.getName();
				// 文件类型
				String contentType = "application/octet-stream";
				// 解决下载文件时文件名乱码问题
				responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName);
				// 响应的格式是:
				responseHeaders.set("content-type", contentType);
				responseHeaders.set("Content-Length", String.valueOf(fileSize));

				
				IoUtil.write(response, true, data);
			} catch (Exception e) {
				// 捕获此异常表示拥护停止下载
				e.printStackTrace();
				LogFormat.info("error :" + e.getMessage());
			}
		}
		
		protected void readVideo(HttpExchange exchange) throws IOException {
			try {
				String name = getQueryParam(exchange, "name");
				{
					LogFormat.info("name :" + name);
				}

				File dir = new File(name);
				if (!dir.exists()) {
					OutputStream response = exchange.getResponseBody();
					exchange.sendResponseHeaders(200, 0);
					IoUtil.write(response, true, "".getBytes());
					return;
				}

				File file = new File(name + "/video");

				if (!file.exists()) {
					OutputStream response = exchange.getResponseBody();
					exchange.sendResponseHeaders(200, 0);
					IoUtil.write(response, true, "".getBytes());
					return;
				}

				if (file.list().length == 0) {
					OutputStream response = exchange.getResponseBody();
					exchange.sendResponseHeaders(200, 0);
					IoUtil.write(response, true, "".getBytes());
					return;
				}

				File[] videoFileUnused = file.listFiles(new FileFilter() {
					@Override
					public boolean accept(File pathname) {
						return !ArrayUtil.contains(pathname.list(), "remove") && !pathname.getPath().contains("conf");
					}
				});

				List<File> videoFileUnusedList = SortFileUtil.sortVideo(file.getPath(), videoFileUnused);

				for (File file2 : videoFileUnusedList) {
					FileUtil.del(name + "/video/未使用.conf");
					FileUtil.appendString(file2.getPath(), name + "/未使用.conf", "utf-8");
				}

				if (videoFileUnused.length == 0) {
					LogFormat.info("视频已经使用完");
					OutputStream response = exchange.getResponseBody();
					exchange.sendResponseHeaders(200, 0);
					IoUtil.write(response, true, "".getBytes());
					return;
				}

				JSONArray array = new JSONArray();

				File videoFile = videoFileUnusedList.get(0);

				{
					LogFormat.info("vidoeFIle: " + videoFile.getPath());
				}

//				File imgFile = new File(videoFile.getPath() + "/result.mp4_1.png");
//				if(imgFile.exists()) {
//					imgFile.delete();
//				}
//				
//				File imgFile2 = new File(videoFile.getPath() + "/result.mp4_2.png");
//				if(imgFile2.exists()) {
//					imgFile2.delete();
//				}
//				
//				File imgFile3 = new File(videoFile.getPath() + "/result.mp4_3.png");
//				if(imgFile3.exists()) {
//					imgFile3.delete();
//				}
//			
				BaiduUtil.check(name);

				byte[] data1 = FileUtil.readBytes(videoFile.getPath() + "/result.mp4_1.png");
				String base64_1 = DatatypeConverter.printBase64Binary(data1);

				byte[] data2 = FileUtil.readBytes(videoFile.getPath() + "/result.mp4_2.png");
				String base64_2 = DatatypeConverter.printBase64Binary(data2);

				byte[] data3 = FileUtil.readBytes(videoFile.getPath() + "/result.mp4_3.png");
				String base64_3 = DatatypeConverter.printBase64Binary(data3);

				array.add(base64_1);
				array.add(base64_2);
				array.add(base64_3);

				String data = array.toString();

				Headers responseHeaders = exchange.getResponseHeaders();
				OutputStream response = exchange.getResponseBody();

				long fileSize = data.length();
				// 通知客户端允许断点续传，响应格式为：Accept-Ranges: bytes
				responseHeaders.set("Accept-Ranges", "bytes");
				// 通知客户端使用的是断点续传协议，即返回206状态：
				exchange.sendResponseHeaders(200, fileSize);
				// 文件名
				String fileName = file.getName();
				// 文件类型
				String contentType = "application/octet-stream";
				// 解决下载文件时文件名乱码问题
				responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName);
				// 响应的格式是:
				responseHeaders.set("content-type", contentType);
				responseHeaders.set("Content-Length", String.valueOf(fileSize));

				// 增加一个文件已经删除的标识
				File removeFlgFile = new File(videoFile.getPath() + "/remove");
				removeFlgFile.createNewFile();

				IoUtil.write(response, true, data.getBytes());
			} catch (Exception e) {
				// 捕获此异常表示拥护停止下载
				e.printStackTrace();
				LogFormat.info("error :" + e.getMessage());

				OutputStream response = exchange.getResponseBody();
				exchange.sendResponseHeaders(200, 0);
				IoUtil.write(response, true, "".getBytes());
			}
		}
	
		/**
		 * 图片动起来
		 * 
		 * @param exchange
		 * @throws IOException
		 */
		protected void firstOrderMotion(HttpExchange exchange) throws IOException {
			// 获取上传文件路径 相对路径 //开头
			String filePath = getQueryParam(exchange, "filePath");

			LogFormat.info("filePath : " + filePath);

			// 获取上传图片的base64位字符串
			InputStream input = exchange.getRequestBody();
			String base64 = IoUtil.read(input, "UTF-8");
			// 图片保存本地
			PicUtil.convertBase64ToImage(base64, filePath);

			String cmd = "activate.bat && conda activate paddle_env && cd " + BASE_PATH
					+ "//PaddleGAN//applications && python -u tools/first-order-demo.py   --driving_video " + BASE_PATH
					+ "//3.MOV   --source_image " + BASE_PATH + filePath + "  --relative   --adapt_scale     --output "
					+ BASE_PATH + filePath + "      --image_size 512    --face_enhancement";

			LogFormat.info("cmd : " + cmd);

			// 调用执行视频命令
			CmdUtil.executeCmdCommand(cmd);

			OutputStream response = exchange.getResponseBody();
			IoUtil.writeObj(response, false, "SUCCESS");
		}
	}

	public static String getQueryParam(HttpExchange request, String name) {
		if (StringUtils.isBlank(name)) {
			return null;
		}
		String s = request.getRequestURI().getQuery();
		if (StringUtils.isBlank(s)) {
			return null;
		}
		try {
			s = URLDecoder.decode(s, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		String[] values = parseQueryString(s).get(name);
		if (values != null && values.length > 0) {
			return values[values.length - 1];
		} else {
			return null;
		}
	}

	public static Map<String, String[]> parseQueryString(String s) {
		String valArray[] = null;
		if (s == null) {
			throw new IllegalArgumentException();
		}
		if (s.contains("?")) {
			s = s.substring(s.indexOf("?") + 1);
		}
		Map<String, String[]> ht = new HashMap<String, String[]>();
		StringTokenizer st = new StringTokenizer(s, "&");
		while (st.hasMoreTokens()) {
			String pair = (String) st.nextToken();
			int pos = pair.indexOf('=');
			if (pos == -1) {
				continue;
			}
			String key = pair.substring(0, pos);
			String val = pair.substring(pos + 1, pair.length());
			if (ht.containsKey(key)) {
				String oldVals[] = (String[]) ht.get(key);
				valArray = new String[oldVals.length + 1];
				for (int i = 0; i < oldVals.length; i++) {
					valArray[i] = oldVals[i];
				}
				valArray[oldVals.length] = val;
			} else {
				valArray = new String[1];
				valArray[0] = val;
			}
			ht.put(key, valArray);
		}
		return ht;
	}
}
